#!/usr/bin/env bash
#COLOURS
bl="\033[1;30m" bu="\033[1;34m" re="\033[1;31m" ge="\033[1;32m" cd="\033[1;36m" ye="\033[1;33m" pk="\033[1;35m" ed="\033[0m"

if [ "$(uname)" == "Linux" ]; then
    if [ "$EUID" -ne 0 ]; then
    	echo -e "[*]$ye 您必须在Linux上以root用户身份运行此程序.$ed"
     	echo -e "[*]$bu 请输入你的密码$ed"
        exec sudo ./downr1n.sh $@
    fi
else
    if [ "$EUID" = "0" ]; then
        echo -e "[*]$ye 在Mac上不需要以Root权限运行，会损坏文件.$ed"
        exit 1
    fi
fi

mkdir -p logs
mkdir -p boot
mkdir -p ipsw/extracted
mainDir=$(pwd)
set -e

log="last".log
cd logs
touch "$log"
cd ..

{

echo -e "[*]$ye 当前运行命令:`if [ $EUID = 0 ]; then echo " sudo"; fi` ./downr1n.sh $@ $ed"



# =========
# Variables
# =========
version="3.0"
os=$(uname)
dir="$(pwd)/binaries/$os"
max_args=2
arg_count=0
dataa="2024.03.31"
if [ ! -d "ramdisk/" ]; then
    git clone https://github.com/dualra1n/ramdisk.git --depth 1
fi

# =========
# Functions
# =========
remote_cmd() {
    sleep 1
    "$dir"/sshpass -p 'alpine' ssh -o StrictHostKeyChecking=no -p2222 root@localhost "$@"
    sleep 1
}

remote_cp() {
    sleep 1
    "$dir"/sshpass -p 'alpine' scp -r -o StrictHostKeyChecking=no -P2222 $@

    sleep 1
}

step() {
    rm -f .entered_dfu
    for i in $(seq "$1" -1 0); do
        if [[ -e .entered_dfu ]]; then
            rm -f .entered_dfu
            break
        fi
        if [[ $(get_device_mode) == "dfu" || ($1 == "10" && $(get_device_mode) != "none") ]]; then
            touch .entered_dfu
        fi &
        printf '\r\e[K\e[1;36m%s (%d)' "$2" "$i"
        sleep 1
    done
    printf '\e[0m\n'
}

print_help() {
    cat << EOF
    Usage: $0 [Options] [ subcommand | iOS 版本 ]. 请把ipsw固件放入 ipsw目录
    iOS 15 - 14.0 强制降级工具 ./downr1n --downgrade 15.7 (15.7是要降级的版本)
    Options参数:
    --downgrade         不完美降级,如果降级14系统无法启动,可以加上参数 --localboot 或 --fsboot ,这可以修复一些引导启动的问题
    --dfuhelper         DFU模式助手，帮助你进入这个模式
    --jailbreak         使用pogo越狱. 用法:./downr1n --jailbreak 14.2
    --taurine           使用牛磺酸taurine越狱. 用法:./downr1n --jailbreak 14.2 --taurine
    --boot              引导启动设备
    --keyServer         使用此选项解决Key解密服务器问题 用法: --downgrade 14.8 --keyServer
    --dont-restore      这将不使用futurerestore进行刷机枪机, 仅仅是创建引导文件
    --debug             调试程序

Subcommands:
    clean               清除所有文件



iOS版本为你的IPSW固件版本.
从DFU模式启动时需要此项.
EOF
}

parse_opt() {
    case "$1" in
        --)
            no_more_opts=1
            ;;
        --downgrade)
            downgrade=1
            ;;
        --boot)
            boot=1
            ;;
        --jailbreak)
            jailbreak=1
            ;;
        --taurine)
            taurine=1
            ;;
        --keyServer)
            keyServer=1
            ;;
        --fixBoot)
            fixBoot=1
            ;;
        --dont-restore)
            dontRestore=1
            ;;
        --localboot)
            local=1
            ;;
        --fsboot)
            fsboot=1
            ;;
        --dfuhelper)
            dfuhelper=1
            ;;
        --debug)
            debug=1
            ;;
        --help)
            print_help
            exit 0
            ;;
        *)
            echo "[-] 使用 $1.  $0 --help 查看帮助."
            exit 1;
    esac
}

parse_arg() {
    arg_count=$((arg_count + 1))
    case "$1" in
        dfuhelper)
            dfuhelper=1
            ;;
        clean)
            clean=1
            ;;
        *)
            version="$1"
            ;;
    esac
}

parse_cmdline() {
    for arg in $@; do
        if [[ "$arg" == --* ]] && [ -z "$no_more_opts" ]; then
            parse_opt "$arg";
        elif [ "$arg_count" -lt "$max_args" ]; then
            if [[ "$arg" == *"ipsw"* ]]; then
                ipsw=$arg
            else
                parse_arg "$arg";
            fi
        else
            echo -e "[-]$ye 参数太多. 请使用 $0 --help 查看帮助. $ed";
            exit 1;
        fi
    done
}

recovery_fix_auto_boot() {
    "$dir"/irecovery -c "setenv auto-boot true"
    "$dir"/irecovery -c "saveenv"
}

_info() {
    if [ "$1" = 'recovery' ]; then
        echo $("$dir"/irecovery -q | grep "$2" | sed "s/$2: //")
    elif [ "$1" = 'normal' ]; then
        echo $("$dir"/ideviceinfo | grep "$2: " | sed "s/$2: //")
    fi
}

_pwn() {
    pwnd=$(_info recovery PWND)
    if [ "$pwnd" = "" ]; then
        echo -e "[*]$bu 进入Pwndfu模式$ed"
        "$dir"/gaster pwn
        sleep 2
        #"$dir"/gaster reset
        #sleep 1
    fi
}

_reset() {
        echo -e "[*]$bu 重置DFU状态$ed"
        "$dir"/gaster reset
}

get_device_mode() {
    if [ "$os" = "Darwin" ]; then
        sp="$(system_profiler SPUSBDataType 2> /dev/null)"
        apples="$(printf '%s' "$sp" | grep -B1 'Vendor ID: 0x05ac' | grep 'Product ID:' | cut -dx -f2 | cut -d' ' -f1 | tail -r)"
    elif [ "$os" = "Linux" ]; then
        apples="$(lsusb | cut -d' ' -f6 | grep '05ac:' | cut -d: -f2)"
    fi
    local device_count=0
    local usbserials=""
    for apple in $apples; do
        case "$apple" in
            12a8|12aa|12ab)
            device_mode=normal
            device_count=$((device_count+1))
            ;;
            1281)
            device_mode=recovery
            device_count=$((device_count+1))
            ;;
            1227)
            device_mode=dfu
            device_count=$((device_count+1))
            ;;
            1222)
            device_mode=diag
            device_count=$((device_count+1))
            ;;
            1338)
            device_mode=checkra1n_stage2
            device_count=$((device_count+1))
            ;;
            4141)
            device_mode=pongo
            device_count=$((device_count+1))
            ;;
        esac
    done
    if [ "$device_count" = "0" ]; then
        device_mode=none
    elif [ "$device_count" -ge "2" ]; then
        echo -e "$bu [-] 请只连接一台设备 $ed" > /dev/tty
        kill -30 0
        exit 1;
    fi
    if [ "$os" = "Linux" ]; then
        usbserials=$(cat /sys/bus/usb/devices/*/serial)
    elif [ "$os" = "Darwin" ]; then
        usbserials=$(printf '%s' "$sp" | grep 'Serial Number' | cut -d: -f2- | sed 's/ //')
    fi
    if grep -qE '(ramdisk tool|SSHRD_Script) (Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec) [0-9]{1,2} [0-9]{4} [0-9]{2}:[0-9]{2}:[0-9]{2}' <<< "$usbserials"; then
        device_mode=ramdisk
    fi
    echo "$device_mode"
}

_wait() {
    if [ "$(get_device_mode)" != "$1" ]; then
        echo -e "[*]$bu 等待设备进入 $1 模式"
    fi

    while [ "$(get_device_mode)" != "$1" ]; do
        sleep 1
    done

    if [ "$1" = 'recovery' ]; then
        recovery_fix_auto_boot;
    fi
}


_dfuhelper() {
    if [ "$(get_device_mode)" = "dfu" ]; then
        echo -e "[*]$bu 设备已经进入DFU模式$ed"
        return;
    fi

    local step_one;
    deviceid=$( [ -z "$deviceid" ] && _info normal ProductType || echo $deviceid )
    if [[ "$1" = 0x801* && "$deviceid" != *"iPad"* ]]; then
        step_one="按住音量减 + 电源键"
    else
        step_one="按住返回键 + 电源键"
    fi
    echo -e "[*]$bu 按任意键开始进入DFU模式$ed"
    read -n 1 -s
    step 3 "请准备"
    step 4 "$step_one" &
    sleep 3
    "$dir"/irecovery -c "reset" &
    sleep 1
    if [[ "$1" = 0x801* && "$deviceid" != *"iPad"* ]]; then
        step 10 '松开 电源键, 继续按住 音量减'
    else
        step 10 '松开 电源键, 继续按住 返回键'
    fi
    sleep 1

    if [ "$(get_device_mode)" = "recovery" ]; then
        _dfuhelper
    fi

    if [ "$(get_device_mode)" = "dfu" ]; then
        echo -e "[*]$bu 成功进入DFU模式!$ed"
    else
        echo -e "[*]$bu 进入DFU模式失败,请重新运行程序!$ed"
       _detect
       _dfuhelper
    fi
}

_do_localboot() {
    ask
    while true; do
        read -r answer
        case "$(echo "$answer" | tr '[:upper:]' '[:lower:]')" in
            yes)
                echo -e "[*]$bu 你的选择是 YES. 所以启动iBoot本地引导...$ed"
                echo -e "[*]$bu 使用krnl修补内核.... $ed"
                if [[ "$deviceid" == *'iPhone8'* ]] || [[ "$deviceid" == *'iPad6'* ]] || [[ "$deviceid" == *'iPad5'* ]]; then
                    python3 -m pyimg4 im4p create -i work/$(if [ "$taurine" = "1" ]; then echo "kcache.patched"; else echo "kcache.patchedB"; fi)  -o work/krnl.im4p -f krnl --extra work/kpp.bin --lzss >/dev/null
                else
                    python3 -m pyimg4 im4p create -i work/$(if [ "$taurine" = "1" ]; then echo "kcache.patched"; else echo "kcache.patchedB"; fi)  -o work/krnl.im4p -f krnl --lzss >/dev/null
                fi
                python3 -m pyimg4 img4 create -p work/krnl.im4p -o work/kernelcachd -m work/IM4M >/dev/null
                remote_cp work/kernelcachd root@localhost:/mnt6/"$active"/System/Library/Caches/com.apple.kernelcaches/ >/dev/null

                 if [ "$os" = 'Linux' ]; then
                    sed -i 's/\/\kernelcache/\/\kernelcachd/g' work/iBEC.dec
                 else
                    LC_ALL=C sed -i.bak -e 's/s\/\kernelcache/s\/\kernelcachd/g' work/iBEC.dec
                 fi

                "$dir"/iBoot64Patcher work/iBEC.dec work/iBEC.patched -b "-v wdt=-1 debug=0x2014e `if [ "$cpid" = '0x8960' ] || [ "$cpid" = '0x7000' ] || [ "$cpid" = '0x7001' ]; then echo "-restore"; fi`" -n -l >/dev/null
                "$dir"/img4 -i work/iBEC.patched -o work/iBEC.img4 -M work/IM4M -A -T "$(if [[ "$cpid" == *"0x801"* ]]; then echo "ibss"; else echo "ibec"; fi)" >/dev/null
                cp -v work/iBEC.img4 "boot/${deviceid}"
                break
                ;;
            no)
                echo -e "$bu[*] 你得答案是NO. 所以没有激活本地iBoot启动.$ed"
                break
                ;;
            *)
                echo -e "$bu[*] 无效答案.$ed"
                usage
                ;;
        esac
    done
}

usage() {
    echo -e "[*]$bu 请输入YES或者NO回答 (不区分大小写)$ed"
}

ask() {
    echo -e "[*]$bu 您想激活iBoot本地启动路径吗？YES或NO.(输入YES或者NO)$ed"
    echo -e "[*]$bu 激活此iBoot本地启动可以帮助避免很多问题，并且通常更稳定.$ed"
    echo -e "[*]$bu 如果您激活了它,您将需要 选择4选项 来引导启动降级的系统.$ed"
    echo -e "[*]$bu 如果iBoot本地启动破坏了您的启动（比如您无法启动），请执行 ./downr1n.sh --downgrade (14.2) --dont-restore 来修复文件.$ed"
    echo -e "[*]$re 请在下方输入你的选择(YES或者NO):$ed"
}

_kill_if_running() {
    if (pgrep -u root -x "$1" &> /dev/null > /dev/null); then
        # yes, it's running as root. kill it
        sudo killall $1 &> /dev/null
    else
        if (pgrep -x "$1" &> /dev/null > /dev/null); then
            killall $1 &> /dev/null
        fi
    fi
}


_runFuturerestore() {
    read -p "按回车键,开始运行futurestore进行刷机,您的设备将开始刷机 <-"
    rm -rf /tmp/futurerestore/
    if [ "$os" == "Linux" ]; then
        sudo -u $SUDO_USER \
        "$dir"/futurerestore -t blobs/"$deviceid"-"$version".shsh2 --use-pwndfu --skip-blob \
        --rdsk work/rdsk.im4p --rkrn work/krnl.im4p \
        --latest-sep "$HasBaseband" "$ipsw"
    else
        "$dir"/futurerestore -t blobs/"$deviceid"-"$version".shsh2 --use-pwndfu --skip-blob \
        --rdsk work/rdsk.im4p --rkrn work/krnl.im4p \
        --latest-sep "$HasBaseband" "$ipsw"
    fi
}

_detect() {
    # Get device's iOS version from ideviceinfo if in normal mode
    echo -e "$ge[*] 等待设备连接...$ed"
    while [ "$(get_device_mode)" = "none" ]; do
        sleep 1;
    done
    echo $(echo -e "[*]$bu 当前设备是: $(get_device_mode) 模式 $ed" | sed 's/dfu/DFU/')

    if grep -E 'pongo|checkra1n_stage2|diag' <<< "$(get_device_mode)"; then
        echo -e "[*]$bu 检测到的设备处于不受支持的模式 '$(get_device_mode)' $ed"
        exit 1;
    fi

    if [ "$(get_device_mode)" != "normal" ] && [ -z "$version" ] && [ "$dfuhelper" != "1" ]; then
        echo -e "[*]$bu 非正常模式启动，必须输入设备的iOS版本 $ed"
        exit
    fi

    if [ "$(get_device_mode)" = "ramdisk" ]; then
        # If a device is in ramdisk mode, perhaps iproxy is still running?
        _kill_if_running iproxy
        echo -e "[*]$bu 重启设备连接SSH Ramdisk $ed"
        if [ "$os" = 'Linux' ]; then
            sudo "$dir"/iproxy 2222 22 >/dev/null &
        else
            "$dir"/iproxy 2222 22 >/dev/null &
        fi
        sleep 1
        remote_cmd "/sbin/reboot"
        _kill_if_running iproxy
        _wait recovery
    fi

    if [ "$(get_device_mode)" = "normal" ]; then
        version=${version:-$(_info normal ProductVersion)}
        arch=$(_info normal CPUArchitecture)
        if [ "$arch" = "arm64e" ]; then
            echo -e "[-]$bu 永远不支持非arm64设备,永不支持$ed"
            exit
        fi
        echo -e "[*]$bu 已连接: $(_info normal ProductType) iOS版本是: $version!"

        echo -e "[*]$bu 进入恢复模式...稍等10秒钟 $ed"
        "$dir"/ideviceenterrecovery $(_info normal UniqueDeviceID)
        _wait recovery
    fi
}

_boot() {
    _pwn
    sleep 1
    _reset
    sleep 1

    echo -e "$ge[*] 启动设备...$ed"

    "$dir"/irecovery -f "blobs/"$deviceid"-"$version".shsh2"
    sleep 1

    if [[ ! "$cpid" == *"0x801"* ]]; then
        "$dir"/irecovery -f "boot/${deviceid}/iBSS.img4"
        sleep 1
    fi

    "$dir"/irecovery -f "boot/${deviceid}/iBEC.img4"
    sleep 3

    if [ "$local" = "1" ]; then
        echo -e "$ge[*] 启动中...$ed"
        echo -e "$ge[*] 您的设备现在使用本地文件引导到系统:)$ed"
        exit;
    fi

    if [[ "$cpid" == *"0x801"* ]]; then
        "$dir"/irecovery -c "go"
        sleep 2
    else
       "$dir"/irecovery -c "bootx"
        sleep 2

    fi


    "$dir"/irecovery -f "boot/${deviceid}/devicetree.img4"
    sleep 1

    "$dir"/irecovery -c "devicetree"
    sleep 1

    "$dir"/irecovery -v -f "boot/${deviceid}/trustcache.img4"

    "$dir"/irecovery -c "firmware"
    sleep 1

    "$dir"/irecovery -f "boot/${deviceid}/kernelcache.img4"
    sleep 1

    "$dir"/irecovery -c bootx
    exit;
}

_exit_handler() {
    if [ "$os" = "Darwin" ]; then
        killall -CONT AMPDevicesAgent AMPDeviceDiscoveryAgent MobileDeviceUpdater || true
    fi

    [ $? -eq 0 ] && exit
    echo -e "[*] $re 当前代码报错,请检查日志$ed"

    if [ -d "logs" ]; then
        cd logs
        mv "$log" FAIL_${log}
        cd ..
    fi

    echo -e "[*] $re 当前代码报错,请检查日志$ed"
}
trap _exit_handler EXIT


# ============
# Dependencies
# ============

if [ "$os" = "Linux"  ]; then
    chmod +x getSSHOnLinux.sh
    ./getSSHOnLinux.sh &
fi

if [ "$os" = 'Linux' ]; then
    linux_cmds='lsusb'
fi

for cmd in unzip python3 rsync git ssh scp killall sudo grep pgrep ${linux_cmds}; do
    if ! command -v "${cmd}" > /dev/null; then
        echo -e "[-] $re '${cmd}' 命令没有安装, 请先安装此命令 $ed";
        cmd_not_found=1
    fi
done
if [ "$cmd_not_found" = "1" ]; then
    exit 1
fi

# Check for pyimg4
packages=("pyimg4")
 for package in "${packages[@]}"; do
    if ! python3 -c 'import pkgutil; exit(not pkgutil.find_loader("lzss") and not pkgutil.find_loader("pyimg4"))'; then
     echo -e "[*] $re 本电脑有安装pyimg4.请按任意键开始安装.或者按Ctrl + C 取消降级$ed"
    read -n 1 -s
    python3 -m pip install fastapi aiohttp ujson wikitextparser uvicorn pyimg4 pyliblzfse lzss -U -i https://pypi.tuna.tsinghua.edu.cn/simple/
    fi
done

 # LZSS gets its own check
packages=("lzss")
for package in "${packages[@]}"; do
    if ! python3 -c "import pkgutil; exit(not pkgutil.find_loader('$package'))"; then
        echo -e "[-] $re '${cmd}' 命令没有安装, 请先安装此命令 $ed";
        read -n 1 -s
        rm -rf "$dir"/pylzss
        git clone https://gitee.com/dkxuanye/pylzss.git "$dir"/pylzss
        cd "$dir"/pylzss
        git checkout "8efcda0"
        python3 "$dir"/pylzss/setup.py install
        cd "$mainDir"
        rm -rf "$dir"/pylzss
    fi
done


# Update submodules

# Re-create work dir if it exists, else, make it
if [ -e work ]; then
    rm -rf work
    mkdir work
else
    mkdir work
fi

chmod +x "$dir"/*

# ============
# Start
# ============

echo -e "$bu[*] | ━━ downr1n 强制降级工具 | 版本 3.0 |更新日期:$dataa$ed"
echo -e "$bu[*] |本工具由edwi编写, 感谢 sunst0rm和所有为此付出的人们 $ed"
sleep 1
echo ""
echo -e "$bl ============================================================$ed"
echo ""
echo -e "$bu    ======== downr1n 强制降级  iOS13-14-15 ======== $ed"
echo ""
echo -e "$pk    ======== *玄烨品果 * 汉化整理 * 尊重原创 * ========$ed"
echo ""
echo -e "$bl ====================== dkxuanye.cn ==========================$ed"
echo ""

parse_cmdline "$@"

if [ "$debug" = "1" ]; then
    set -o xtrace
fi

if [ "$clean" = "1" ]; then
    rm -rf  work blobs/ boot/"$deviceid"/
    echo -e "$bu 清理本地创建的文件 $ed"
    exit
fi


# Get device's iOS version from ideviceinfo if in normal mode
echo -e "[*]$bu 等待设备连接 $ed"
while [ "$(get_device_mode)" = "none" ]; do
    sleep 1;
done
echo $(echo -e "[*]$bu 当前设备是: $(get_device_mode) 模式 $ed" | sed 's/dfu/DFU/')

if grep -E 'pongo|checkra1n_stage2|diag' <<< "$(get_device_mode)"; then
    echo -e "[*]$bu 检测到的设备处于不受支持的模式 '$(get_device_mode)' $ed"
    exit 1;
fi

if [ "$(get_device_mode)" != "normal" ] && [ -z "$version" ] && [ "$dfuhelper" != "1" ]; then
    echo -e "[*]$bu 非正常模式启动，必须输入设备的iOS版本 $ed"
    exit
fi

if [ "$(get_device_mode)" = "ramdisk" ]; then
    # If a device is in ramdisk mode, perhaps iproxy is still running?
    _kill_if_running iproxy
    echo -e "[*]$bu 重启设备连接SSH Ramdisk $ed"
    if [ "$os" = 'Linux' ]; then
        sudo "$dir"/iproxy 2222 22 >/dev/null &
    else
        "$dir"/iproxy 2222 22 >/dev/null &
    fi
    sleep 2
    remote_cmd "/usr/sbin/nvram auto-boot=false"
    remote_cmd "/sbin/reboot"
    _kill_if_running iproxy
    _wait recovery
fi

if [ "$(get_device_mode)" = "normal" ]; then
    version=${version:-$(_info normal ProductVersion)}
    arch=$(_info normal CPUArchitecture)
    if [ "$arch" = "arm64e" ]; then
        echo -e "[-]$bu 不支持非arm64设备,永不支持$ed"
        exit
    fi
    echo -e "[*]$bu 已连接: $(_info normal ProductType) iOS版本是: $version!"

    echo -e "[*]$bu 进入恢复模式...稍等10秒钟 $ed"
    if [ ! $("$dir"/ideviceenterrecovery $(_info normal UniqueDeviceID)) ]; then
      echo "[/] 如果您的设备无法进入恢复模式，请尝试强制重新启动并将其置于恢复模式"
    fi
    _wait recovery
fi

_detect

# Grab more info
echo -e "$bu[*] 读取设备信息...$ed"
cpid=$(_info recovery CPID)
model=$(_info recovery MODEL)
deviceid=$(_info recovery PRODUCT)

echo -e "$bu[*] ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo -e "$bu[*] 设备CPID:$cpid$ed"
echo -e "$bu[*] 设备型号:$model$ed"
echo -e "$bu[*] 设备芯片:$deviceid$ed"
echo -e "$bu[*] ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"

if [ "$dfuhelper" = "1" ]; then
    echo -e "$bu[*] 正在运行DFU帮助程序$ed"
    _dfuhelper "$cpid"
    exit
fi

ipswurl=$(curl -sL "https://api.ipsw.me/v4/device/$deviceid?type=ipsw" | "$dir"/jq '.firmwares | .[] | select(.version=="'$version'")' | "$dir"/jq -s '.[0] | .url' --raw-output)


# Have the user put the device into DFU
if [ "$(get_device_mode)" != "dfu" ]; then
    recovery_fix_auto_boot;
    _dfuhelper "$cpid" || {
        echo -e "$bu[-] 无法进入DFU模式，请再次运行downr1.sh$ed"
        exit -1
    }
fi
sleep 2


if [ "$boot" = "1" ]; then # call boot in order to boot it
    _boot
fi

# understand my code is more difficult that understand a programing language fr
if [ ! $(ls ipsw/*.ipsw) ]; then
    echo -e "$bu[-] 没有IPSW固件,所以我们要下载它, 将下载用于$deviceid和版本$version的固件, 您想更改版本（YES）还是（NO）"
    while true; do
        read -r answer
        case "$(echo "$answer" | tr '[:upper:]' '[:lower:]')" in
            yes)
                echo -e "$bu[*] 你得选择是 YES. 请输入您想要安装的版本:$ed"
                read -r version
                ipswurl=$(curl -sL "https://api.ipsw.me/v4/device/$deviceid?type=ipsw" | "$dir"/jq '.firmwares | .[] | select(.version=="'$version'")' | "$dir"/jq -s '.[0] | .url' --raw-output)
                break
                ;;
            no)
                echo -e "$bu[*] 你的选择是 NO. 所以使用 $version.$ed"
                break
                ;;
            *)
                echo -e "$bu[*] 回答错误.$ed"
                usage
                ;;
        esac
    done
    # downloader by @sasa
    echo -e "$bu[*] 下载固件中, 需要几分钟时间.$ed"
    curl -Lo ipsw/$deviceid-$version.ipsw "$ipswurl" "-#"
    ipsw=$(find ipsw/ -name "*.ipsw")
 fi


    # =========
    # extract ipsw
    # =========
mkdir -p ipsw/extracted/$deviceid
mkdir -p ipsw/extracted/$deviceid/$version

extractedIpsw="ipsw/extracted/$deviceid/$version/"

if [[ "$ipsw" == *".ipsw" ]]; then
    echo -e "[-]$bu 在ipsw/目录中有多个ipsw固件,请删除无效固件,并重试$ed"
else
    ipsw=()
    for file in ipsw/*.ipsw; do
        ipsw+=("$file")
    done


    if [ ${#ipsw[@]} -eq 0 ]; then
        echo -e "[-]$bu IPSW固件没有找到$ed"
        exit;
    else
        for file in "${ipsw[@]}"; do
            if [[ "$file" = *"$version"* ]]; then
                while true
                do
                    echo -e "[-]$bu 我们找到 $file, 您想使用它来降级吗? 请输入, "yes" 或 "no"$ed"
                    read result
                    if [ "$result" = "yes" ]; then
                        echo "$file"
                        unset ipsw
                        ipsw=$file
                        break
                    elif [ "$result" = "no" ]; then
                        break
                    fi
                done
            fi
        done
    fi
fi

# Check if ipsw is an array
if [[ "$(declare -p ipsw)" =~ "declare -a" ]]; then
    while true
    do
        echo -e "$bu[*] 请输入数字选择你要的固件$ed"
        for i in "${!ipsw[@]}"; do
            echo "$((i+1)). ${ipsw[i]}"
        done
        read -p "输入你的选择: " choice

        if [[ ! "$choice" =~ ^[1-${#ipsw[@]}]$ ]]; then
            echo -e "$bu[*] 错误的选择$ed"
        else
            echo -e "$bu[*] 我们将使用 ${ipsw[$choice-1]}$ed"
            ipsw="${ipsw[$choice-1]}"
            break
        fi
    done
fi

unzip -o $ipsw BuildManifest.plist -d work/ >/dev/null

if [ "$downgrade" = "1" ] || [ "$jailbreak" = "1" ]; then
    echo -e "$bu[*] 正在为你检查固件,请稍等$ed"
    ipswDevicesid=()
    ipswVers=""
    ipswDevId=""
    counter=0

    while [ ! "$deviceid" = "$ipswDevId" ]
    do
        if [ "$os" = 'Darwin' ]; then
            ipswDevId=$(/usr/bin/plutil -extract "SupportedProductTypes.$counter" xml1 -o - work/BuildManifest.plist | grep '<string>' |cut -d\> -f2 |cut -d\< -f1 | head -1)
        else
            ipswDevId=$("$dir"/PlistBuddy work/BuildManifest.plist -c "Print SupportedProductTypes:$counter" | sed 's/"//g')
        fi

        ipswDevicesid[counter]=$ipswDevId

        if [ "$ipswDevId" = "" ]; then # this is to stop looking for more devices as it pass the limit and can't find deviceid
            break
        fi

        let "counter=counter+1"
    done


    if [ "$ipswDevId" = "" ]; then
        echo -e "$bu[/] 看起来固件有问题,请删除重试$ed"

        for element in "${ipswDevicesid[@]}"; do
            cho -e "$bu[*] 这是支持固件的设备: $element$ed"
        done

        echo -e "$bu[*] 然而你的设备 $deviceid 不在支持的列表里$ed"
        read -p "想要继续吗 ? 按回车键继续 ..."
    fi


    echo -e "$bu[*] 检查固件的iOS版本$ed"
    if [ "$os" = 'Darwin' ]; then
        ipswVers=$(/usr/bin/plutil -extract "ProductVersion" xml1 -o - work/BuildManifest.plist | grep '<string>' |cut -d\> -f2 |cut -d\< -f1 | head -1)
    else
        ipswVers=$("$dir"/PlistBuddy work/BuildManifest.plist -c "Print ProductVersion" | sed 's/"//g')
    fi

    if [[ ! "$version" = "$ipswVers" ]]; then
      echo -e "$bu[*] 固件的iOS版本是: $ipswVers, 你输入的是: $version"
      read -p "错误的版本选择, 按回车键继续,或者按 Ctrl+C 取消"
    fi

fi

version_code=""

if [ "$downgrade" = "1" ]; then
    if [ "$os" = 'Darwin' ]; then
        version_code=$(/usr/bin/plutil -extract "ProductBuildVersion" xml1 -o - work/BuildManifest.plist | grep '<string>' |cut -d\> -f2 |cut -d\< -f1 | head -1)
    else
        version_code=$("$dir"/PlistBuddy work/BuildManifest.plist -c "Print ProductBuildVersion" | sed 's/"//g')
    fi

fi

if [ "$downgrade" = "1" ] || [ "$jailbreak" = "1" ]; then
    # extracting ipsw
    echo -e "$bu[*] 解压ipsw固件,请稍等$ed" # this will extract the ipsw into ipsw/extracted
    unzip -n $ipsw -d $extractedIpsw >/dev/null
    #cp -v "$extractedIpsw/BuildManifest.plist" work/
    echo -e "$bu[*] 固件已解压完成...$ed"
fi

if [ "$jailbreak" = "1" ]; then
    cp  "$extractedIpsw$(awk "/""${model}""/{x=1}x&&/iBoot[.]/{print;exit}" work/BuildManifest.plist | grep '<string>' |cut -d\> -f2 |cut -d\< -f1)" "work/"
    ramdisk/"$os"/gaster decrypt work/"$(awk "/""${model}""/{x=1}x&&/iBoot[.]/{print;exit}" work/BuildManifest.plist | grep '<string>' |cut -d\> -f2 |cut -d\< -f1 | sed 's/Firmware[/]all_flash[/]//')" work/iBEC.dec
    ramdisk/"$os"/gaster reset
fi

# ============
# Ramdisk
# ============

# Dump blobs, and install pogo if needed
if [ true ]; then
    mkdir -p blobs

    cd ramdisk
    chmod +x sshrd.sh
    echo -e "$bu[*] 创建ramdisk系统...$ed"
    ./sshrd.sh "15.6"

    echo -e "$bu[*] 启动ramdisk系统...$ed"
    ./sshrd.sh boot
    cd ..
    # remove special lines from known_hosts
    if [ -f ~/.ssh/known_hosts ]; then
        if [ "$os" = "Darwin" ]; then
            sed -i.bak '/localhost/d' ~/.ssh/known_hosts
            sed -i.bak '/127\.0\.0\.1/d' ~/.ssh/known_hosts
        elif [ "$os" = "Linux" ]; then
            sed -i '/localhost/d' ~/.ssh/known_hosts
            sed -i '/127\.0\.0\.1/d' ~/.ssh/known_hosts
        fi
    fi

    # Execute the commands once the rd is booted
    if [ "$os" = 'Linux' ]; then
        sudo "$dir"/iproxy 2222 22 >/dev/null &
    else
        "$dir"/iproxy 2222 22 >/dev/null &
    fi

    if ! ("$dir"/sshpass -p 'alpine' ssh -ostricthostkeychecking=false -ouserknownhostsfile=/dev/null -o StrictHostKeyChecking=no -q -p2222 root@localhost "echo connected" &> /dev/null); then
        echo -e "$bu[*] 等待设备启动...$ed"
    fi

    while ! ("$dir"/sshpass -p 'alpine' ssh -ostricthostkeychecking=false -ouserknownhostsfile=/dev/null -o StrictHostKeyChecking=no -q -p2222 root@localhost "echo connected" &> /dev/null); do
        sleep 1
    done

    if [ "$(remote_cmd "/usr/bin/mgask HasBaseband | grep -E 'true|false'")" = "true" ]; then
        HasBaseband='--latest-baseband'
    else
        HasBaseband='--no-baseband'
    fi

    echo -e "$bu[*] 挂载系统...$ed"
    if [[ "$version" = "13."* ]]; then
        remote_cmd "/sbin/mount_apfs /dev/disk0s1s1 /mnt1"
    fi

    if [ ! "$downgrade" = "1" ] && [[ ! "$version" = "13."* ]]; then
        remote_cmd "/usr/bin/mount_filesystems 2>/dev/null"
    elif [ "$downgrade" = "1" ] && [[ ! "$version" = "13."* ]]; then
        remote_cmd "/usr/bin/mount_filesystems_nouser 2>/dev/null"
    fi

    has_active=$(remote_cmd "ls /mnt6/active" 2> /dev/null)
    if [ ! "$has_active" = "/mnt6/active" ] && [[ ! "$version" = "13."* ]]; then
        echo "[!] 解密文件不存在,请手动创建它"
        echo "    使用UDID名字文件夹名字目录在/mnt6/active"
        echo "    完成后重新使用SSH连接挂载"
        echo "    ssh root@localhost -p 2222"
        exit
    else
        active=$(remote_cmd "cat /mnt6/active" 2> /dev/null)
    fi

    mkdir -p "boot/${deviceid}"

    if [ ! -e blobs/"$deviceid"-"$version".shsh2 ]; then
        remote_cmd "cat /dev/rdisk1" | dd of=dump.raw bs=256 count=$((0x4000))
        "$dir"/img4tool --convert -s blobs/"$deviceid"-"$version".shsh2 dump.raw
        echo -e "$bu[*] 转换blob文件...$ed"
        sleep 3
        rm dump.raw

    fi

    "$dir"/img4tool -e -s blobs/"$deviceid"-"$version".shsh2 -m work/IM4M >/dev/null
    echo -e "$bu[*] 解密证书文件...$ed"

    echo -e "$bu[*] 检查设备的iOS版本...$ed"
    remote_cp other/plutil root@localhost:/mnt1/

    SystemVersion=$(remote_cmd "chmod +x /mnt1/plutil && /mnt1/plutil -key ProductVersion /mnt1/System/Library/CoreServices/SystemVersion.plist")
    echo -e "$bu[*] 当前设备的iOS版本是: $SystemVersion$ed"

    if [ "$jailbreak" = "1" ]; then
        echo "[*] Patching kernel" # this will send and patch the kernel
        cp "$extractedIpsw$(awk "/""${model}""/{x=1}x&&/kernelcache.release/{print;exit}" work/BuildManifest.plist | grep '<string>' |cut -d\> -f2 |cut -d\< -f1)" "work/"
        cp  work/"$(awk "/""${model}""/{x=1}x&&/kernelcache.release/{print;exit}" work/BuildManifest.plist | grep '<string>' |cut -d\> -f2 |cut -d\< -f1)" work/kernelcache

        if [[ "$deviceid" == "iPhone8"* ]] || [[ "$deviceid" == "iPad6"* ]] || [[ "$deviceid" == *'iPad5'* ]]; then
            python3 -m pyimg4 im4p extract -i work/kernelcache -o work/kcache.raw --extra work/kpp.bin >/dev/null
        else
            python3 -m pyimg4 im4p extract -i work/kernelcache -o work/kcache.raw >/dev/null
        fi

        "$dir"/Kernel64Patcher work/kcache.raw work/kcache.patched $(if [[ "$version" = "15."* ]]; then echo "-e -o -r -b15"; fi) $(if [[ "$version" = "14."* ]]; then echo "-b"; fi) $(if [[ "$version" = "13."* ]]; then echo "-b13 -n"; fi) $(if [ ! "$taurine" = "1" ]; then echo "-l"; fi) >/dev/null

        sysDir="/mnt6/$active/"
        if [[ "$version" = "13."* ]]; then
            sysDir="/mnt1/"
        fi
        remote_cp work/kcache.patched root@localhost:"$sysDir"System/Library/Caches/com.apple.kernelcaches/kcache.patched >/dev/null
        #remote_cp boot/"${deviceid}"/kernelcache.img4 "root@localhost:/mnt6/$active/System/Library/Caches/com.apple.kernelcaches/kernelcache" >/dev/null
        remote_cp binaries/$(if [[ "$version" = "13."* ]]; then echo "Kernel13Patcher.ios"; else echo "Kernel15Patcher.ios"; fi) root@localhost:/mnt1/private/var/root/Kernel15Patcher.ios >/dev/null
        remote_cmd "/usr/sbin/chown 0 /mnt1/private/var/root/Kernel15Patcher.ios"
        remote_cmd "/bin/chmod 755 /mnt1/private/var/root/Kernel15Patcher.ios"
        sleep 1
        if [ ! $(remote_cmd "/mnt1/private/var/root/Kernel15Patcher.ios ${sysDir}System/Library/Caches/com.apple.kernelcaches/kcache.patched ${sysDir}System/Library/Caches/com.apple.kernelcaches/kcache.patchedB  2>/dev/null") ]; then
            echo -e "$bu[*] 内核文件已经修补过...$ed"
        fi

        sleep 2
        remote_cp root@localhost:"$sysDir"System/Library/Caches/com.apple.kernelcaches/kcache.patchedB work/ # that will return the kernelpatcher in order to be patched again and boot with it

        if [[ "$deviceid" == *'iPhone8'* ]] || [[ "$deviceid" == *'iPad6'* ]] || [[ "$deviceid" == *'iPad5'* ]]; then
            python3 -m pyimg4 im4p create -i "work/$(if [ "$taurine" = "1" ]; then echo "kcache.patched"; else echo "kcache.patchedB"; fi)" -o work/kcache.im4p -f rkrn --extra work/kpp.bin --lzss >/dev/null
        else
            python3 -m pyimg4 im4p create -i "work/$(if [ "$taurine" = "1" ]; then echo "kcache.patched"; else echo "kcache.patchedB"; fi)" -o work/kcache.im4p -f rkrn --lzss >/dev/null
        fi

        remote_cmd "rm -f ${sysDir}System/Library/Caches/com.apple.kernelcaches/kcache.raw ${sysDir}System/Library/Caches/com.apple.kernelcaches/kcache.patched ${sysDir}System/Library/Caches/com.apple.kernelcaches/kcache.im4p"
        python3 -m pyimg4 img4 create -p work/kcache.im4p -o work/kernelcache.img4 -m work/IM4M >/dev/null

        #"$dir"/kerneldiff work/kcache.raw work/kcache.patchedB work/kc.bpatch
        #"$dir"/img4 -i work/"$(awk "/""${model}""/{x=1}x&&/kernelcache.release/{print;exit}" work/BuildManifest.plist | grep '<string>' |cut -d\> -f2 |cut -d\< -f1)" -o work/kernelcache.img4 -M work/IM4M -T rkrn -P work/kc.bpatch `if [ "$os" = 'Linux' ]; then echo "-J"; fi`
        #remote_cp root@localhost:/mnt6/$active/System/Library/Caches/com.apple.kernelcaches/kernelcachd work/kernelcache.img4
        cp -v "work/kernelcache.img4" "boot/${deviceid}"
        echo -e "$bu[*] 内核修补完成...$ed"

        remote_cmd "/bin/mkdir -p /mnt1/Applications/dualra1n-loader.app && /bin/mkdir -p /mnt1/Applications/trollstore.app"

        echo -e "$bu[*] dualra1n-loader安装中...$ed"
        unzip -o other/dualra1n-loader.ipa -d other/
        remote_cp other/Payload/dualra1n-loader.app root@localhost:/mnt1/Applications/

        echo -e "$bu[*] 系统快照保存...$ed"
        if [ ! "$(remote_cmd "/usr/bin/snaputil -c orig-fs /mnt1")" ]; then
            echo -e "$bu[*] 系统快照已存在,跳过 ...$ed"
        fi

        if [ ! $(remote_cmd "trollstoreinstaller TV") ]; then
            echo -e "$bu[/] 安装巨魔到TV应用...$ed"
        fi

        echo "[*] Fixing dualra1n-loader"
        if [ ! $(remote_cmd "chmod +x /mnt1/Applications/dualra1n-loader.app/dualra1n* && /usr/sbin/chown 33 /mnt1/Applications/dualra1n-loader.app/dualra1n-loader && /bin/chmod 755 /mnt1/Applications/dualra1n-loader.app/dualra1n-helper && /usr/sbin/chown 0 /mnt1/Applications/dualra1n-loader.app/dualra1n-helper" ) ]; then
            echo -e "$bu[*] 使用巨魔安装 dualra1n-loader或者其他办法$ed"
        fi

        if [[ "$version" = "13."* ]]; then
            echo -e "$bu[*] 完成!...重启设备并再次引导启动 $ed"
            remote_cmd "/sbin/reboot"
            exit;
        fi

        if [ "$taurine" = 1 ]; then
            echo -e "$bu[*] 安装牛磺酸越狱... $ed"
            remote_cp other/taurine/* root@localhost:/mnt1/
            echo -e "$bu[*] 牛磺酸复制成功... $ed"
            _do_localboot
            echo -e "$bu[*] 现在您的设备已经越狱成功... $ed"
            remote_cmd "/sbin/reboot"
            exit;
        fi

        echo -e "$bu[*] 安装JBINIT jailbreak$ed"
        echo -e "$bu[*] 文件复制中.... $ed"
        remote_cmd "rm -rf /mnt1/jbin /mnt1/.installed_palera1n"
        sleep 1
        remote_cmd "mkdir -p /mnt1/jbin/binpack /mnt1/jbin/loader.app"
        sleep 1

        # this is the jailbreak of palera1n being installing

        remote_cp -r other/rootfs/* root@localhost:/mnt1/
        remote_cmd "ldid -s /mnt1/jbin/launchd /mnt1/jbin/jbloader /mnt1/jbin/jb.dylib"
        remote_cmd "chmod +rwx /mnt8/jbin/launchd /mnt8/jbin/jbloader"
        remote_cmd "tar -xvf /mnt1/jbin/binpack/binpack.tar -C /mnt1/jbin/binpack/"
        sleep 1
        remote_cmd "rm /mnt1/jbin/binpack/binpack.tar"
        remote_cmd "/usr/sbin/nvram auto-boot=true"
        echo -e "$bu[*] 完成复制.... $ed"
        _do_localboot
        echo -e "$bu[*] 越狱完成, 再次重启设备.... $ed"
        remote_cmd "/sbin/reboot"
        exit;

    fi

    echo -e "$bu[*] 修补kernel ...$ed" # this will send and patch the kernel

    cp "$extractedIpsw$(awk "/""${model}""/{x=1}x&&/kernelcache.release/{print;exit}" work/BuildManifest.plist | grep '<string>' |cut -d\> -f2 |cut -d\< -f1)" "work/kernelcache"

    if [[ "$deviceid" == "iPhone8"* ]] || [[ "$deviceid" == "iPad6"* ]] || [[ "$deviceid" == *'iPad5'* ]]; then
        python3 -m pyimg4 im4p extract -i work/kernelcache -o work/kcache.raw --extra work/kpp.bin >/dev/null
    else
        python3 -m pyimg4 im4p extract -i work/kernelcache -o work/kcache.raw >/dev/null
    fi

    echo -e "$bu[*] 已解压...$ed"

    echo -e "$bu[*] 重启进入恢复模式...$ed"
    remote_cmd "/usr/sbin/nvram auto-boot=false"
    remote_cmd "/sbin/reboot"
    sleep 10

    if [ "$(get_device_mode)" = "dfu" ]; then
      echo -e "$bu[*] 进入DFU模式失败, 请手动进入DFU模式,然后再按回车键继续...$ed"
    read -p "如果你已经进入DFU模式, 请按回车键继续"
        "$dir"/gaster pwn
    else
        _wait recovery
        sleep 4
        _dfuhelper "$cpid"
        sleep 3
    fi



    echo -e "$bu[*] 修补启动文件...$ed"
    if [ "$downgrade" = "1" ]; then
        sleep 1

        mkdir -p boot/"$deviceid"


        if [ "$fixBoot" = "1" ]; then # i put it because my friend tested on his ipad and that does not boot so when we download all file from the internet so not extracting ipsw that boot fine idk why

            cd work
            #that will download the files needed
            sleep 1
            "$dir"/pzb -g "$(awk "/""${model}""/{x=1}x&&/iBSS[.]/{print;exit}" BuildManifest.plist | grep '<string>' |cut -d\> -f2 |cut -d\< -f1)" "$ipswurl"
            "$dir"/pzb -g "$(awk "/""${model}""/{x=1}x&&/iBoot[.]/{print;exit}" BuildManifest.plist | grep '<string>' |cut -d\> -f2 |cut -d\< -f1)" "$ipswurl"
            "$dir"/pzb -g "$(awk "/""${model}""/{x=1}x&&/DeviceTree[.]/{print;exit}" BuildManifest.plist | grep '<string>' |cut -d\> -f2 |cut -d\< -f1)" "$ipswurl"
            "$dir"/pzb -g "$(awk "/""${model}""/{x=1}x&&/kernelcache.release/{print;exit}" BuildManifest.plist | grep '<string>' |cut -d\> -f2 |cut -d\< -f1)" "$ipswurl"

            if [ "$os" = 'Darwin' ]; then
                "$dir"/pzb -g Firmware/"$(/usr/bin/plutil -extract "BuildIdentities".0."Manifest"."OS"."Info"."Path" xml1 -o - BuildManifest.plist | grep '<string>' |cut -d\> -f2 |cut -d\< -f1 | head -1)".trustcache "$ipswurl"
            else
                "$dir"/pzb -g Firmware/"$(../binaries/Linux/PlistBuddy BuildManifest.plist -c "Print BuildIdentities:0:Manifest:OS:Info:Path" | sed 's/"//g')".trustcache "$ipswurl"
            fi
            cd ..
        else
            #that will extract the files needed
            cp  "$extractedIpsw$(awk "/""${model}""/{x=1}x&&/iBSS[.]/{print;exit}" work/BuildManifest.plist | grep '<string>' |cut -d\> -f2 |cut -d\< -f1)" "work/"
            cp  "$extractedIpsw$(awk "/""${model}""/{x=1}x&&/iBoot[.]/{print;exit}" work/BuildManifest.plist | grep '<string>' |cut -d\> -f2 |cut -d\< -f1)" "work/"
            cp  "$extractedIpsw$(awk "/""${model}""/{x=1}x&&/DeviceTree[.]/{print;exit}" work/BuildManifest.plist | grep '<string>' |cut -d\> -f2 |cut -d\< -f1)" "work/"
            cp  "$extractedIpsw$(awk "/""${model}""/{x=1}x&&/kernelcache.release/{print;exit}" work/BuildManifest.plist | grep '<string>' |cut -d\> -f2 |cut -d\< -f1)" "work/"

            if [ "$os" = 'Darwin' ]; then
                cp "$extractedIpsw"/Firmware/"$(/usr/bin/plutil -extract "BuildIdentities".0."Manifest"."OS"."Info"."Path" xml1 -o - work/BuildManifest.plist | grep '<string>' |cut -d\> -f2 |cut -d\< -f1 | head -1)".trustcache work/
            else
                cp "$extractedIpsw"/Firmware/"$(binaries/Linux/PlistBuddy work/BuildManifest.plist -c "Print BuildIdentities:0:Manifest:OS:Info:Path" | sed 's/"//g')".trustcache work/
            fi
        fi

        if [ "$os" = "Darwin" ]; then
            "$dir"/img4 -i work/"$(/usr/bin/plutil -extract "BuildIdentities".0."Manifest"."OS"."Info"."Path" xml1 -o - work/BuildManifest.plist | grep '<string>' |cut -d\> -f2 |cut -d\< -f1 | head -1)".trustcache -o work/trustcache.img4 -M work/IM4M -T rtsc >/dev/null
        else
            "$dir"/img4 -i work/"$(binaries/Linux/PlistBuddy work/BuildManifest.plist -c "Print BuildIdentities:0:Manifest:OS:Info:Path" | sed 's/"//g')".trustcache -o work/trustcache.img4 -M work/IM4M -T rtsc >/dev/null
        fi

        echo -e "$bu[*] 完成修补启动文件... $ed"
        sleep 2

        echo -e "$bu[*] 解密iboot、ibss文件... $ed"
        "$dir"/gaster decrypt work/"$(awk "/""${model}""/{x=1}x&&/iBSS[.]/{print;exit}" work/BuildManifest.plist | grep '<string>' |cut -d\> -f2 |cut -d\< -f1 | sed 's/Firmware[/]dfu[/]//')" work/iBSS.dec

        sleep 1
        "$dir"/iBoot64Patcher work/iBSS.dec work/iBSS.patched -n >/dev/null
        "$dir"/img4 -i work/iBSS.patched -o work/iBSS.img4 -M work/IM4M -A -T ibss >/dev/null

        "$dir"/gaster decrypt work/"$(awk "/""${model}""/{x=1}x&&/iBoot[.]/{print;exit}" work/BuildManifest.plist | grep '<string>' |cut -d\> -f2 |cut -d\< -f1 | sed 's/Firmware[/]all_flash[/]//')" work/iBEC.dec >/dev/null
        sleep 1

        if [ "$local" = "1" ]; then
            echo -e "$bu[*] 修补iboot文件... $ed"
            if [ "$os" = 'Linux' ]; then
                sed -i 's/\/\kernelcache/\/\kernelcachd/g' work/iBEC.dec
            else
                LC_ALL=C sed -i.bak -e 's/s\/\kernelcache/s\/\kernelcachd/g' work/iBEC.dec
            fi
        fi

        "$dir"/iBoot64Patcher work/iBEC.dec work/iBEC.patched -b "-v wdt=-1 `if [ "$cpid" = '0x8960' ] || [ "$cpid" = '0x7000' ] || [ "$cpid" = '0x7001' ]; then echo "-restore"; fi`" -n "$(if [ "$local" = "1" ]; then echo "-l"; fi)" >/dev/null
        "$dir"/img4 -i work/iBEC.patched -o work/iBEC.img4 -M work/IM4M -A -T "$(if [[ "$cpid" == *"0x801"* ]]; then echo "ibss"; else echo "ibec"; fi)" >/dev/null

        if [ "$keyServer" = "1" ]; then
            echo -e "$bu[*] 修补iboot\ibec文件,方便futurerestore刷机... $ed"
            mkdir -p $TMPDIR/futurerestore
            cp  "$extractedIpsw$(awk "/""${model}""/{x=1}x&&/iBEC[.]/{print;exit}" work/BuildManifest.plist | grep '<string>' |cut -d\> -f2 |cut -d\< -f1)" "work/"
            "$dir"/gaster decrypt work/"$(awk "/""${model}""/{x=1}x&&/iBEC[.]/{print;exit}" work/BuildManifest.plist | grep '<string>' |cut -d\> -f2 |cut -d\< -f1 | sed 's/Firmware[/]dfu[/]//')" work/iBECFuture.dec >/dev/null
            "$dir"/iBoot64Patcher work/iBECFuture.dec work/iBECFuture.patched -b "rd=md0 nand-enable-reformat=0x1 -v -restore debug=0x2014e keepsyms=0x1 amfi=0xff amfi_allow_any_signature=0x1 amfi_get_out_of_my_way=0x1 cs_enforcement_disable=0x1" -n >/dev/null
            "$dir"/img4 -i work/iBECFuture.patched -o "$TMPDIR/futurerestore/ibec.$model.$version_code.patched.img4" -M work/IM4M -A -T ibec >/dev/null
            cp -av work/iBSS.img4 $TMPDIR/futurerestore/ibss.$model.$version_code.patched.img4
            echo -e "$bu[*] 为futurerestore成功创建文件... $ed"
        fi

        echo -e "$bu[*] 修补内核文件... $ed"
        "$dir"/Kernel64Patcher work/kcache.raw work/kcache.patched $(if [[ "$version" = "15."* ]]; then echo "-e -o -r -b15"; fi) $(if [[ "$version" = "14."* ]]; then echo "-b"; fi) $(if [[ "$version" = "13."* ]]; then echo "-b13 -n"; fi) >/dev/null

        if [[ "$deviceid" == *'iPhone8'* ]] || [[ "$deviceid" == *'iPad6'* ]] || [[ "$deviceid" == *'iPad5'* ]]; then
            python3 -m pyimg4 im4p create -i work/kcache.patched -o work/kcache.im4p -f rkrn --extra work/kpp.bin --lzss >/dev/null
        else
            python3 -m pyimg4 im4p create -i work/kcache.patched -o work/kcache.im4p -f rkrn --lzss >/dev/null
        fi

        python3 -m pyimg4 img4 create -p work/kcache.im4p -o work/kernelcache.img4 -m work/IM4M >/dev/null

        echo -e "$bu[*] 修补内核文件,方便futurerestore刷机... $ed"
        "$dir"/Kernel64Patcher work/kcache.raw work/krnl.patched -a -b >/dev/null

        if [[ "$deviceid" == "iPhone8"* ]] || [[ "$deviceid" == "iPad6"* ]] || [[ "$deviceid" == *'iPad5'* ]]; then
            python3 -m pyimg4 im4p create -i work/krnl.patched -o work/krnl.im4p --extra work/kpp.bin -f rkrn --lzss >/dev/null
        else
            python3 -m pyimg4 im4p create -i work/krnl.patched -o work/krnl.im4p -f rkrn --lzss >/dev/null
        fi

        echo -e "$bu[*] 修补DeviceTree... $ed"
        "$dir"/img4 -i work/"$(awk "/""${model}""/{x=1}x&&/DeviceTree[.]/{print;exit}" work/BuildManifest.plist | grep '<string>' |cut -d\> -f2 |cut -d\< -f1 | sed 's/Firmware[/]all_flash[/]//')" work/devicetree.img4 -M work/IM4M -T rdtr >/dev/null

        if [ "$os" = "Darwin" ]; then
            cp "$extractedIpsw$(/usr/bin/plutil -extract "BuildIdentities".0."Manifest"."RestoreRamDisk"."Info"."Path" xml1 -o - work/BuildManifest.plist | grep '<string>' |cut -d\> -f2 |cut -d\< -f1 | head -1)" "work/" >/dev/null
        else
            cp "$extractedIpsw$(binaries/Linux/PlistBuddy work/BuildManifest.plist -c "Print BuildIdentities:0:Manifest:RestoreRamDisk:Info:Path" | sed 's/"//g')" "work/" >/dev/null
        fi

        if [ "$os" = "Darwin" ]; then
            "$dir"/img4 -i work/"$(/usr/bin/plutil -extract "BuildIdentities".0."Manifest"."RestoreRamDisk"."Info"."Path" xml1 -o - work/BuildManifest.plist | grep '<string>' |cut -d\> -f2 |cut -d\< -f1 | head -1)" -o work/ramdisk.dmg >/dev/null
        else
            "$dir"/img4 -i work/"$(binaries/Linux/PlistBuddy work/BuildManifest.plist -c "Print BuildIdentities:0:Manifest:RestoreRamDisk:Info:Path" | sed 's/"//g')" -o work/ramdisk.dmg >/dev/null
        fi

        echo -e "$bu[*] 修补启动文件restored_external asr,并且保存到ramdisk...$ed"
        if [ "$os" = "Darwin" ]; then
            hdiutil attach work/ramdisk.dmg -mountpoint /tmp/SSHRD >/dev/null
            mounted="/tmp/SSHRD"

            "$dir"/asr64_patcher $mounted/usr/sbin/asr work/patched_asr >/dev/null
            "$dir"/ldid -e $mounted/usr/sbin/asr > work/asr.plist
            "$dir"/ldid -Swork/asr.plist work/patched_asr
            chmod -R 755 work/patched_asr
            rm $mounted/usr/sbin/asr

            mv work/patched_asr $mounted/usr/sbin/asr


            if [[ ! "$version" = "13."* ]]; then
                cp $mounted/usr/local/bin/restored_external work/restored_external
                "$dir"/restored_external64_patcher work/restored_external work/patched_restored_external >/dev/null
                "$dir"/ldid -e work/restored_external > work/restored_external.plist
                "$dir"/ldid -Swork/restored_external.plist work/patched_restored_external
                chmod -R 755 work/patched_restored_external
                rm $mounted/usr/local/bin/restored_external
                mv work/patched_restored_external $mounted/usr/local/bin/restored_external
            fi


            hdiutil detach -force /tmp/SSHRD
        else

            "$dir"/hfsplus work/ramdisk.dmg extract /usr/sbin/asr work/asr >/dev/null
            "$dir"/asr64_patcher work/asr work/patched_asr >/dev/null
            "$dir"/ldid -e work/asr > work/asr.plist
            "$dir"/ldid -Swork/asr.plist work/patched_asr
            chmod 755 work/patched_asr

            "$dir"/hfsplus work/ramdisk.dmg rm /usr/sbin/asr
            "$dir"/hfsplus work/ramdisk.dmg add work/patched_asr /usr/sbin/asr
            "$dir"/hfsplus work/ramdisk.dmg chmod 100755 /usr/sbin/asr

            if [[ ! "$version" = "13."* ]]; then

                "$dir"/hfsplus work/ramdisk.dmg extract /usr/local/bin/restored_external work/restored_external >/dev/null
                "$dir"/restored_external64_patcher work/restored_external work/patched_restored_external >/dev/null
                "$dir"/ldid -e work/restored_external > work/restored_external.plist
                "$dir"/ldid -Swork/restored_external.plist work/patched_restored_external
                chmod 755 work/patched_restored_external
                "$dir"/hfsplus work/ramdisk.dmg rm /usr/local/bin/restored_external
                "$dir"/hfsplus work/ramdisk.dmg add work/patched_restored_external /usr/local/bin/restored_external
                "$dir"/hfsplus work/ramdisk.dmg chmod 100755 /usr/local/bin/restored_external
            fi
        fi

        python3 -m pyimg4 im4p create -i work/ramdisk.dmg -o work/rdsk.im4p -f rdsk >/dev/null

        cp -v work/*.img4 "boot/${deviceid}" # copying all file img4 to boot

        echo -e "$bu[*] 启动文件修补成功... $ed"

        echo -e "$bu[*] 检查LLB文件是否已经替换过... $ed"

        if [ ! -e "boot/${deviceid}/.llbreplaced" ]; then
            echo -e "$bu[*] 修补ipsw中的llb以避免错误的dfu模式$ed"
            echo -e "$bu[=] 嗨,我需要你写下这个设备所在的iOS版本或它所在的iOS的版本（如果这个设备已经降级）, 大多数时候都是iOS的最新版本.如果你想跳过这个, 写0（不建议跳过这个,因为这样可以避免错误的dfu模式）"

            while true
            do
                if [ ! "$version" = "$SystemVersion" ] && [ ! "$SystemVersion" = "" ]; then
                    echo -e "$bu[*] 版本已经选择!. 我们将使用 $SystemVersion$ed"
                    ipswLLB=$(curl -sL "https://api.ipsw.me/v4/device/$deviceid?type=ipsw" | "$dir"/jq '.firmwares | .[] | select(.version=="'$SystemVersion'")' | "$dir"/jq -s '.[0] | .url' --raw-output)
                else
                    read result
                    if [ "$result" = "0" ]; then
                        echo -e "$bu[*] 跳过... $ed"
                        break
                    fi
                    ipswLLB=$(curl -sL "https://api.ipsw.me/v4/device/$deviceid?type=ipsw" | "$dir"/jq '.firmwares | .[] | select(.version=="'$result'")' | "$dir"/jq -s '.[0] | .url' --raw-output)
                fi

                sleep 1

                cd work/
                if [ $("$dir"/pzb -g "$(awk "/""${model}""/{x=1}x&&/LLB[.]/{print;exit}" BuildManifest.plist | grep '<string>' |cut -d\> -f2 |cut -d\< -f1)" "$ipswLLB" >/dev/null) ]; then
                    echo -e "$bu[*] 下载LLB文件失败... $ed"
                fi
                cd ..

                if [ ! -e "work/$(awk "/""${model}""/{x=1}x&&/LLB[.]/{print;exit}" work/BuildManifest.plist | grep '<string>' |cut -d\> -f2 |cut -d\< -f1 | sed 's/Firmware[/]all_flash[/]//')" ]; then
                    echo -e "$bu[-] 下载llb时出错,请检查iOS版本,然后重新输入. 如果此错误经常发生，请使用0, 跳过llb下载(不建议)$ed"
                else
                    echo -e "$bu[*] 下载当前LLB文件... $ed"
                    echo -e "$bu[*] 打包LLB文件到IPSW固件... $ed"
                    cp -f work/$(awk "/""${model}""/{x=1}x&&/LLB[.]/{print;exit}" work/BuildManifest.plist | grep '<string>' |cut -d\> -f2 |cut -d\< -f1 | sed 's/Firmware[/]all_flash[/]//') "$extractedIpsw/Firmware/all_flash/$(awk "/""${model}""/{x=1}x&&/LLB[.]/{print;exit}" work/BuildManifest.plist | grep '<string>' |cut -d\> -f2 |cut -d\< -f1 | sed 's/Firmware[/]all_flash[/]//')"
                    cd $extractedIpsw
                    zip --update "$mainDir/$ipsw" Firmware/all_flash/"$(awk "/""${model}""/{x=1}x&&/LLB[.]/{print;exit}" BuildManifest.plist | grep '<string>' |cut -d\> -f2 |cut -d\< -f1 | sed 's/Firmware[/]all_flash[/]//')" Firmware/all_flash//$(awk "/""${model}""/{x=1}x&&/LLB[.]/{print;exit}" BuildManifest.plist | grep '<string>' |cut -d\> -f2 |cut -d\< -f1 | sed 's/Firmware[/]all_flash[/]//')
                    cd "$mainDir"
                    echo -e "$bu[*] 替换LLB文件成功... $ed"

                    touch "boot/${deviceid}/.llbreplaced"
                    break
                fi
            done
        fi
        sleep 1

        set +e

        "$dir"/gaster reset >/dev/null
        sleep 1
        "$dir"/irecovery -f "blobs/"$deviceid"-"$version".shsh2" >/dev/null

        if [ "$dontRestore" = "1" ]; then
            echo -e "$bu[*] 启动文件创建完成,现在可以启动设备... $ed"
            exit;
        fi

        echo -e "$bu[*] 执行Futurerestore刷机... $ed"
        _runFuturerestore
        sleep 2

        echo -e " 如果futurerestore 刷机失败,请使用下面命令:$ed"
        echo -e "\033[1;33m刷机失败，执行这个命令:\033[0m \033[1m$dir/futurerestore -t blobs/$deviceid-$version.shsh2 --use-pwndfu --skip-blob --rdsk work/rdsk.im4p --rkrn work/krnl.im4p --latest-sep $HasBaseband $ipsw\033[0m"

        echo -e "$bu[*] 如果futurerestore刷机成功,你现在可以引导启动设备... $ed"
    fi
fi


} 2>&1 | tee logs/${log}
